#pragma once
#include <map>
#include <vector>

namespace ly
{
	enum State
	{
		EMPTY,
		EXIST,
		DELETE
	};

	template<class K, class V>
	class HashTables
	{
		struct Elem
		{
			pair<K, V> _val;
			State _state = EMPTY;
		};
	public:
		HashTables(size_t capacity = 10)
			:_ht(capacity)
			,_size(0)
		{}

		bool Insert(const pair<K, V>& val)
		{
			if ((_size * 10) / _ht.capacity() >= 7)
			{
				HashTables<K, V> newht(2 * _ht.capacity());
				for (size_t i = 0; i < _ht.capacity(); i++)
				{
					if (_ht[i]._state == EXIST)
					{
						newht.Insert(_ht[i]._val);
					}
				}
				Swap(newht);
			}

			int hashi = HashFunc(val.first);
			while (_ht[hashi]._state == EXIST)
			{
				if (_ht[hashi]._val.first == val.first)
				{
					return false;
				}
				++hashi;
				hashi %= _ht.capacity();
			}
			_ht[hashi]._val = val;
			_ht[hashi]._state = EXIST;
			++_size;
			return true;
		}

		size_t Find(const K& key)
		{
			int hashi = HashFunc(key);
			while (_ht[hashi]._state != EMPTY)
			{
				if (_ht[hashi]._val.first == key)
				{
					return hashi;
				}

				++hashi;
				hashi %= _ht.capacity();
			}
			return false;
		}

		bool Erase(const K& key)
		{
			size_t hashi = Find(key);
			if (hashi != -1)
			{
				_ht[hashi]._state = DELETE;
				--_size;
				return ture;
			}

			return false;
		}

		size_t Size() const
		{
			return _size;
		}

		bool Empty() const
		{
			return _size == 0;
		}

		void Swap(HashTables<K, V>& ht)
		{
			swap(_size, ht._size);
			_ht.swap(ht._ht);
		}

	private:
		size_t HashFunc(const K& key)
		{
			return key % _ht.capacity();
		}

		vector<Elem> _ht;
		size_t _size;
	};
}